﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace com.zhongjh.Library.Configuration
{
    public class Config
    {
        #region 字段

        private string m_strConfigPath = AppDomain.CurrentDomain.BaseDirectory + "Configuration.xml";
        private static List<ConfigItem> m_lstConfigItemList = null;

        #endregion //end 字段

        #region 公有方法

        /// <summary>
        /// 构造函数
        /// </summary>
        public Config()
        {
            m_lstConfigItemList = null;
            //加载配置文件
            GetConfig();
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="p_strConfigPath">配置文件路径（包括文件名）</param>
        public Config(string p_strConfigPath)
        {
            if (!string.IsNullOrEmpty(p_strConfigPath))
            {
                m_strConfigPath = p_strConfigPath;
                m_lstConfigItemList = null;
            }
            //加载配置文件
            GetConfig();
        }

        /// <summary>
        /// 获取配置信息
        /// </summary>
        /// <returns>所有配置列表</returns>
        public List<ConfigItem> GetConfig()
        {
            if (m_lstConfigItemList != null)
                return m_lstConfigItemList;

            m_lstConfigItemList = new List<ConfigItem>();
            if (File.Exists(m_strConfigPath))
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(m_strConfigPath);
                XmlNodeList configNodeList = xmlDoc.SelectNodes("/Configuration");

                if (configNodeList.Count > 0)
                {
                    foreach (XmlNode currNode in configNodeList[0].ChildNodes)
                    {
                        ConfigItem configItem = new ConfigItem();

                        for (int i1 = 0; i1 < currNode.Attributes.Count; i1++)
                        {
                            foreach (PropertyInfo prop in configItem.GetType().GetProperties())
                            {
                                if (prop.Name.ToLower() == currNode.Attributes[i1].Name && prop.GetValue(configItem, null).GetType() == typeof(string))
                                {
                                    prop.SetValue(configItem, currNode.Attributes[i1].Value, null);
                                    break;
                                }
                            }
                        }

                        for (int i1 = 0; i1 < currNode.ChildNodes.Count; i1++)
                        {
                            ConfigItem child = new ConfigItem(currNode.ChildNodes[i1]);
                            configItem.ChildItems.Add(child);
                        }

                        m_lstConfigItemList.Add(configItem);
                    }
                }
            }
            else
            {
                //配置文件不存在
                m_lstConfigItemList = null;
            }

            return m_lstConfigItemList;
        }

        /// <summary>
        /// 获取配置信息
        /// </summary>
        /// <param name="p_strKey">键</param>
        /// <returns>配置项</returns>
        public ConfigItem GetConfigByKey(string p_strKey)
        {
            ConfigItem result = null;
            foreach (ConfigItem temp in m_lstConfigItemList)
            {
                result = temp.GetItem(p_strKey);
                if (result != null)
                    break;
            }
            return result;
        }

        /// <summary>
        /// 获取配置
        /// </summary>
        /// <param name="p_strKeyPath">名字路径如Key1/Key2</param>
        /// <returns>配置节点</returns>
        public ConfigItem GetConfigByPath(string p_strKeyPath)
        {
            ConfigItem result = null;

            string[] arrNames = p_strKeyPath.Split('/');
            if (arrNames != null && arrNames.Length > 0)
            {
                ConfigItem currentConfigItem = null;
                for (int i1 = 0; i1 <= arrNames.Length; i1++)
                {
                    if (i1 == 0)
                    {
                        foreach (ConfigItem temp in m_lstConfigItemList)
                        {
                            if (temp.Key == arrNames[i1])
                            {
                                currentConfigItem = temp;
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (currentConfigItem != null)
                        {
                            currentConfigItem = currentConfigItem.GetChildItem(arrNames[i1]);
                            if ((i1 + 1) == arrNames.Length)
                            {
                                result = currentConfigItem;
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 保存
        /// </summary>
        public void Save()
        {
            if (m_lstConfigItemList != null)
            {
                XmlDocument xmlDoc = new XmlDocument();
                XmlElement configurationXmlElement = xmlDoc.CreateElement("Configuration");

                foreach (ConfigItem temp1 in m_lstConfigItemList)
                {
                    XmlElement xmlElement = xmlDoc.CreateElement("Item");

                    //获取ConfigItem值到XmlElement
                    foreach (PropertyInfo prop in temp1.GetType().GetProperties())
                    {
                        if (prop.GetValue(temp1) != null
                            && prop.GetValue(temp1, null).GetType() == typeof(string)
                            && !string.IsNullOrEmpty(prop.GetValue(temp1).ToString()))
                            xmlElement.SetAttribute(prop.Name.ToLower(), prop.GetValue(temp1).ToString());
                    }

                    //添加ConfigItem子项到XmlElement
                    foreach (ConfigItem temp2 in temp1.ChildItems)
                    {
                        AddNode(temp2, xmlDoc, xmlElement);
                    }
                    configurationXmlElement.AppendChild(xmlElement);
                }

                xmlDoc.AppendChild(configurationXmlElement);
                xmlDoc.Save(m_strConfigPath);
            }
        }

        #endregion //end 公有方法

        #region 私有方法


        //添加节点
        private void AddNode(ConfigItem p_objConfigItem, XmlDocument p_objXmlDoc, XmlElement p_objXmlElementParent)
        {
            XmlElement xmlElement = p_objXmlDoc.CreateElement("Item");

            //获取ConfigItem值到XmlElement
            foreach (PropertyInfo prop in p_objConfigItem.GetType().GetProperties())
            {
                if (prop.GetValue(p_objConfigItem) != null
                    && prop.GetValue(p_objConfigItem, null).GetType() == typeof(string)
                    && !string.IsNullOrEmpty(prop.GetValue(p_objConfigItem).ToString()))
                {
                    xmlElement.SetAttribute(prop.Name.ToLower(), prop.GetValue(p_objConfigItem).ToString());
                }
            }

            //添加ConfigItem子项到XmlElement
            foreach (ConfigItem temp in p_objConfigItem.ChildItems)
            {
                AddNode(temp, p_objXmlDoc, xmlElement);
            }
            p_objXmlElementParent.AppendChild(xmlElement);
        }

        #endregion //end 私有方法

    }
}
